﻿using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Commands;
using Fuse8.ContentManagementFramework.Domain.Commands.CommandParameters;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;
using System.Collections.Generic;
using System.Linq;

namespace Fuse8.ContentManagementFramework.BizFacade.Services
{
    public class CmsUserInformationService : CmsBusinessService<CmsUserInformation>
    {
        public virtual void CreateUser(CmsUserInformation cmsUserInformation)
        {
            Guard.ArgumentNotNull(cmsUserInformation, "cmsUserInformation");

            var command = DependencyServiceLocator.Current.GetInstance<CmsCreateUpdateUserCommand>();

            var commandParameter = new CmsCreateUpdateUserCommandParameter
            {
                LoginName = cmsUserInformation.LoggedInUser.LoginName,
                UserEmail = cmsUserInformation.LoggedInUser.UserEmail,
                Firstname = cmsUserInformation.LoggedInUser.Firstname,
                Lastname = cmsUserInformation.LoggedInUser.Lastname,
                PasswordHash = cmsUserInformation.LoggedInUser.PasswordHash,
                PasswordSalt = cmsUserInformation.LoggedInUser.PasswordSalt,
                IsSystem = cmsUserInformation.LoggedInUser.IsSystem,
                IsInitial = cmsUserInformation.IsInitial,
                Locale = cmsUserInformation.LoggedInUser.Locale
            };

            TrackingEntityObjectMediator.TrackEntity(commandParameter);
            SiteAwareEntityObjectMediator.SetSiteEntityByCategory(commandParameter, cmsUserInformation.LoggedInUser.SiteCategory);

            command.ConfigureCommand(commandParameter);

            Execute(command);

            cmsUserInformation.LoggedInUser.Id = commandParameter.Id;
        }

        public virtual void UpdateUser(CmsUser user)
        {
            Guard.ArgumentNotNull(user, "user");

            var command = DependencyServiceLocator.Current.GetInstance<CmsCreateUpdateUserCommand>();

            var commandParameter = new CmsCreateUpdateUserCommandParameter
            {
                Id = user.Id,
                LoginName = user.LoginName,
                UserEmail = user.UserEmail,
                Firstname = user.Firstname,
                Lastname = user.Lastname,
                PasswordHash = user.PasswordHash,
                PasswordSalt = user.PasswordSalt,
                IsEnabled = user.IsEnabled,
                IsSystem = user.IsSystem,
                Locale = user.Locale
            };

            TrackingEntityObjectMediator.TrackEntity(commandParameter);
            SiteAwareEntityObjectMediator.SetSiteEntityByCategory(commandParameter, user.SiteCategory);

            command.ConfigureCommand(commandParameter);

            Execute(command);
        }

        public virtual void AssignToGroups(int userId, IEnumerable<CmsUserGroup> userGroups)
        {
            Guard.ArgumentNotNull(userGroups, "userGroups");

            var command = DependencyServiceLocator.Current.GetInstance<CmsUserAssignToGroupsCommand>();

            var commandParameter = new CmsUserAssignToGroupsCommandParameter
            {
                UserId = userId,
                UserGroupIds = userGroups.Select(p => p.Id)
            };

            command.ConfigureCommand(commandParameter);

            Execute(command);
        }

        public virtual void RemoveFromGroups(int userId, IEnumerable<CmsUserGroup> userGroups)
        {
            Guard.ArgumentNotNull(userGroups, "userGroups");

            var command = DependencyServiceLocator.Current.GetInstance<CmsUserAssignToGroupsCommand>();

            var commandParameter = new CmsUserAssignToGroupsCommandParameter
            {
                UserId = userId,
                UserGroupIds = userGroups.Select(p => p.Id),
                IsForRemove = true
            };

            command.ConfigureCommand(commandParameter);

            Execute(command);
        }

        public virtual CmsUserInformation GetUserInformationByLoginName(string loginName, bool allSites = false)
        {
            Guard.ArgumentNotEmpty(loginName, "loginName");

            var command = DependencyServiceLocator.Current.GetInstance<CmsUserGetInformationCommand>();

            var commandParameter = new CmsUserGetInformationCommandParameter
            {
                LoginName = loginName
            };

            if (!allSites)
            {
                SiteAwareEntityObjectMediator.SetSiteEntity(commandParameter);
            }

            command.ConfigureCommand(commandParameter);

            return FindOne(command);
        }

        public IEnumerable<CmsUserInformation> GetAllUserInformationForManagement(int startWith, int pageCapacity, string sortField = null, string sortDirection = null)
        {
            return InternalGetUserInformationForManagement(0, startWith, pageCapacity, sortField, sortDirection);
        }

        public CmsUserInformation GetUserInformationForManagement(int userId)
        {
            return InternalGetUserInformationForManagement(userId, 0, 0, null, null).FirstOrDefault();
        }

        protected virtual IEnumerable<CmsUserInformation> InternalGetUserInformationForManagement(int userId, int startWith, int pageCapacity, string sortField, string sortDirection)
        {
            var command = DependencyServiceLocator.Current.GetInstance<CmsUserInformationForManagementCommand>();

            var commandParameter = new CmsUserInformationForManagementCommandParameter();

            if (userId > 0)
            {
                commandParameter.Id = userId;
            }
            else
            {
                commandParameter.CurrentPage = startWith;
                commandParameter.PageCapacity = pageCapacity;
                commandParameter.SortField = sortField;
                commandParameter.SortDirection = sortDirection;
            }

            SiteAwareEntityObjectMediator.SetSiteEntity(commandParameter);

            command.ConfigureCommand(commandParameter);

            return Find(command);
        }
    }
}